import express from 'express';
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import cors from 'cors';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();
app.use(express.json());
app.use(cors());

const JWT_SECRET = 'your-secret-key';

// Database setup
let db;
(async () => {
  db = await open({
    filename: './database.sqlite',
    driver: sqlite3.Database
  });

  await db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT UNIQUE,
      password TEXT
    );

    CREATE TABLE IF NOT EXISTS todos (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      title TEXT,
      completed BOOLEAN,
      FOREIGN KEY (user_id) REFERENCES users (id)
    );
  `);

  // Create initial admin user
  const adminUser = await db.get('SELECT * FROM users WHERE username = ?', 'admin');
  if (!adminUser) {
    const hashedPassword = await bcrypt.hash('ddd', 10);
    await db.run('INSERT INTO users (username, password) VALUES (?, ?)', 'admin', hashedPassword);
  }
})();

// Middleware to verify JWT token
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (token == null) return res.sendStatus(401);

  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
};

// User registration
app.post('/register', async (req, res) => {
  const { username, password } = req.body;
  try {
    const hashedPassword = await bcrypt.hash(password, 10);
    await db.run('INSERT INTO users (username, password) VALUES (?, ?)', username, hashedPassword);
    res.status(201).json({ message: 'User registered successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Error registering user' });
  }
});

// User login
app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  try {
    const user = await db.get('SELECT * FROM users WHERE username = ?', username);
    if (user && await bcrypt.compare(password, user.password)) {
      const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET);
      res.json({ token });
    } else {
      res.status(400).json({ error: 'Invalid credentials' });
    }
  } catch (error) {
    res.status(500).json({ error: 'Error logging in' });
  }
});

// Create a new todo
app.post('/todos', authenticateToken, async (req, res) => {
  const { title } = req.body;
  try {
    const result = await db.run('INSERT INTO todos (user_id, title, completed) VALUES (?, ?, ?)', req.user.id, title, false);
    res.status(201).json({ id: result.lastID, title, completed: false });
  } catch (error) {
    res.status(500).json({ error: 'Error creating todo' });
  }
});

// Get all todos for a user
app.get('/todos', authenticateToken, async (req, res) => {
  try {
    const todos = await db.all('SELECT * FROM todos WHERE user_id = ?', req.user.id);
    res.json(todos);
  } catch (error) {
    res.status(500).json({ error: 'Error fetching todos' });
  }
});

// Update a todo
app.put('/todos/:id', authenticateToken, async (req, res) => {
  const { title, completed } = req.body;
  try {
    await db.run('UPDATE todos SET title = ?, completed = ? WHERE id = ? AND user_id = ?', title, completed, req.params.id, req.user.id);
    res.json({ message: 'Todo updated successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Error updating todo' });
  }
});

// Delete a todo
app.delete('/todos/:id', authenticateToken, async (req, res) => {
  try {
    await db.run('DELETE FROM todos WHERE id = ? AND user_id = ?', req.params.id, req.user.id);
    res.json({ message: 'Todo deleted successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Error deleting todo' });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));